useEffect 是拿來做什麼的?這件事在我初學 React 時其實相當困惑,就算知道它是React 中設計用來處理「副作用」的 hooks API 好了,但因為它會牽扯到很多很謎的情況,所以一直都覺得很難理解,像是:
直到我看了《React 思維進化》這本書後,才真正理解 useEffect 的核心概念:它的主要功能是將資料的變更同步到副作用的執行中,並且 useEffect 的依賴陣列設計是用來進行效能優化。聽起來很抽象?接下來我會從頭開始說明的正確使用觀念。
什麼是副作用(effect)?
一個函式除了回傳結果外,還會與外部環境互動。像是修改函式外的全域變數、發送 API 請求或直接操作 DOM 元素等。
如果處理不當,會有什麼問題?
那在 React 中,可以利用 useEffect 來做副作用的管理。
基本語法
useEffect(() => {
// 副作用邏輯,例如:打 API 或更新 DOM
return () => {
// 清除副作用(可選),例如:取消訂閱或清理資源
};
}, [dependencies]);
dependencies
發生變化時,setup 函式會被重新執行dependencies 的三種寫法
Object.is
方法來一一比較陣列中所有依賴項目的值與前一次 render 時的版本是否相同,如果都相同的話則會跳過執行本次 render 的 setup 函式 。[]
:這個 setup 函式沒有任何的依賴資料,會被 React 認為在每次 re-render 時可以安全的跳過 setup 函式的執行。作法是元件 render 期間不進行副作用操作,因為副作用的執行可能會阻塞渲染流程,導致效能問題。因此,useEffect 在元件渲染完成後才執行。而且在重新執行副作用前,React 會先清理上一次的副作用,這樣就不會出現多次副作用重複執行、互相影響的情況。
React 的常見執行順序如下:
也因為是這樣來處理副作用的,可以跑跑以下來看執行順序:
import { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('副作用執行: 設置文件標題');
document.title = `你點擊了 ${count} 次`;
return () => {
console.log('清理副作用: 重置標題');
document.title = 'React App';
};
}, [count]); // 當 count 改變時,重新執行副作用
return (
<div>
<p>你點擊了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>點擊我</button>
</div>
);
}
export default Counter;